﻿using GalaSoft.MvvmLight.Messaging;
using PremisPublisher.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;

/*
 
 读取发布配置文件
 * 
 * author：张鹏 
 * date：2016.5
 
 */


namespace PremisPublisher.Common
{
    public class PublisherReader
    {
        public string XMLPATH = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "publishs.xml");
        private string rsa_public_key { get { return Read_Rsa_public_key(); } }
        public IEnumerable<XPublish> Publishs { get { return ReadPublishContent(); } }

        public IEnumerable<XAdditional> Additionals { get { return ReadAttitionalContent(); } }

        public string SourcePath { get { return ReadSourcePath(); } }
        public string SlnPath { get { return ReadSlnPath(); } }

        public string BuildOutputPath { get { return ReadBuildOutputPath(); } }
        public string PublishRootDir { get { return ReadPublishRootDir(); } }

        public string JsHostPath { get { return ReadJsHostPath(); } }
        public static PublisherReader GetInstance()
        { return new PublisherReader(); }

        private PublisherReader()
        {
            if (!System.IO.File.Exists(XMLPATH))
            {
                Messenger.Default.Send<ShowMessageDialogMessage>(new ShowMessageDialogMessage() { Message = "配置文件没找到" });
            }
        }

        public string GetRSAPublicKey()
        {
            return rsa_public_key;
        }

        public string ReadJsHostPath()
        {
            return XDocument.Load(XMLPATH).Element("publishs").Element("JsHost").Attribute("path").Value;
        }

        private string Read_Rsa_public_key()
        {
            return XDocument.Load(XMLPATH).Element("publishs").Element("public_key").Element("RSAKeyValue").ToString();
        }

        private string ReadPublishRootDir()
        {
            return XDocument.Load(XMLPATH).Element("publishs").Element("PublishRootDir").Attribute("path").Value;
        }

        private string ReadBuildOutputPath()
        {
            return XDocument.Load(XMLPATH).Element("publishs").Element("BuildOutput").Attribute("path").Value;
        }

        private string ReadSourcePath()
        {
            return System.IO.Path.GetDirectoryName(XDocument.Load(XMLPATH).Element("publishs").Element("Source").Attribute("path").Value);
        }

        private string ReadSlnPath()
        {
            return XDocument.Load(XMLPATH).Element("publishs").Element("Source").Attribute("path").Value;
        }


        private IEnumerable<XPublish> ReadPublishContent()
        {
            var doc = XDocument.Load(XMLPATH);
            var ps = doc.Element("publishs").Elements("publish");

            string _publishedWebSites = BuildOutputPath + "\\_PublishedWebsites";

            var q = from item in ps
                    select new XPublish(System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value), item.Attribute("target").Value)
                    {
                        Dirs = (from d in item.Element("files").Elements("dir")
                                select new RDir(
                                    System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value, d.Attribute("name").Value),
                                    System.IO.Path.Combine(item.Attribute("target").Value, item.Attribute("source").Value, d.Attribute("name").Value),
                                    d.Attribute("rsa") == null ? "false" : d.Attribute("rsa").Value)).ToList(),
                        Files = (from f in item.Element("files").Elements("file")
                                 select new RFile(
                                     System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value, f.Attribute("path").Value),
                                     System.IO.Path.Combine(item.Attribute("target").Value, item.Attribute("source").Value, f.Attribute("path").Value),
                                     f.Attribute("charset") == null ? "utf-8" : f.Attribute("charset").Value)
                                 {
                                     Reps = f.HasElements ? (from r in f.Element("reps").Elements("rep")
                                             select new KeyValuePair<string, string>(r.Element("old").Value, r.Element("new").Value)
                                             ).ToList(): new List<KeyValuePair<string,string>>()
                                 }
                                 ).ToList()
                    };

            return q;
        }

        public IEnumerable<XPublish> ReadPublishContent1()
        {
            var doc = XDocument.Load(XMLPATH);
            var ps = doc.Element("publishs").Elements("publish");

            string _publishedWebSites = BuildOutputPath + "\\_PublishedWebsites";

            List<XPublish> result = new List<XPublish>();

            foreach (var item in ps)
            {
                var xp = new XPublish(System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value), item.Attribute("target").Value);
                xp.Dirs = new List<RDir>();
                xp.Files = new List<RFile>();

                foreach (var d in item.Element("files").Elements("dir"))
                {
                    var nd = new RDir(
                                    System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value, d.Attribute("name").Value),
                                    System.IO.Path.Combine(item.Attribute("target").Value, item.Attribute("source").Value, d.Attribute("name").Value),
                                    d.Attribute("rsa") == null ? "false" : d.Attribute("rsa").Value);
                    xp.Dirs.Add(nd);
                }

                foreach (var f in item.Element("files").Elements("file"))
                {
                    var rf = new RFile(System.IO.Path.Combine(_publishedWebSites, item.Attribute("source").Value, f.Attribute("path").Value),
                                     System.IO.Path.Combine(item.Attribute("target").Value, item.Attribute("source").Value, f.Attribute("path").Value),
                                     f.Attribute("charset") == null ? "utf-8" : f.Attribute("charset").Value);
                    if (f.HasElements)
                    {
                        foreach (var r in f.Element("reps").Elements("rep"))
                        {
                            var kvp = new KeyValuePair<string, string>(r.Element("old").Value, r.Element("new").Value);
                            rf.Reps.Add(kvp);
                        }
                    }

                    xp.Files.Add(rf);
                }

                result.Add(xp);
            }

            return result;
        }


        private IEnumerable<XAdditional> ReadAttitionalContent()
        {
            var doc = XDocument.Load(XMLPATH);
            var ps = doc.Element("publishs").Elements("additional");

            List<XAdditional> lst = new List<XAdditional>();

            foreach (var item in ps)
            {
                string dest_path = System.IO.Path.Combine(PublishRootDir, item.Attribute("dest_path").Value);

                var xa = new XAdditional(dest_path);

                xa.Files = new List<AdditionalFile>();

                foreach (var i in item.Elements("file"))
                {
                    string target_path = System.IO.Path.Combine(dest_path, System.IO.Path.GetFileName(i.Attribute("path").Value));
                    string src_file = i.Attribute("path").Value;

                    Regex _ = new Regex(@"\$BuildOutputPath\$");
                    src_file = _.Replace(src_file, this.BuildOutputPath);

                    _ = new Regex(@"\$SourcePath\$");
                    src_file = _.Replace(src_file, this.SourcePath);

                    AdditionalFile af = new AdditionalFile(src_file, target_path, i.Attribute("zip") == null ? "0" : i.Attribute("zip").Value);

                    af.Reps = new Dictionary<string, KeyValuePair<string, string>>();

                    foreach (var rep in i.Elements("rep"))
                    {
                        var kv = new KeyValuePair<string, string>(rep.Element("old").Value, rep.Element("new").Value);
                        af.Reps.Add(rep.Attribute("fileinzip").Value, kv);
                    }

                    xa.Files.Add(af);
                }

                lst.Add(xa);

            }

            return lst;
        }

        /// <summary>
        /// 分段RSA加密
        /// </summary>
        /// <param name="filepath"></param>
        /// <returns>错误返回1， 成功返回0</returns>
        public int rsa_crypt(string filepath)
        {

            var content = System.IO.File.ReadAllText(filepath);

            try
            {
                var crypted_content = RSACrypto.Encrypt(content, rsa_public_key);

                System.IO.FileInfo fi = new System.IO.FileInfo(filepath);
                fi.IsReadOnly = false;
                fi.Delete();

                //用加密的内容替换
                System.IO.File.WriteAllText(filepath, crypted_content);

                System.IO.FileInfo nfi = new System.IO.FileInfo(filepath);
                nfi.IsReadOnly = true;
            }
            catch (Exception)
            {
                System.IO.File.WriteAllText(filepath, content);
                return 1;
            }

            return 0;
        }
    }
}
